﻿using CacheExtensions;
using Hangfire;
using Hangfire.Annotations;
using Hangfire.Dashboard;
using Hangfire.InMemory;
using Hangfire.Redis.StackExchange;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using StackExchange.Redis;
namespace HangfireExtensions
{
    public static class HangfireExtension
    {
        public static DateTime? ToLoal(this DateTime? time)
        {
            return time != default ? time.GetValueOrDefault().ToLocalTime() : new Nullable<DateTime>();
        }


        #region 初始化 Redis配置
        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="cacheConfig"></param>
        public static void AddHangfireCore(this IServiceCollection services, IConfigurationSection section)
        {
            // services.AddHttpJob();
            var cacheConfig = section.Get<CacheConfig>() ?? new CacheConfig();

            services.AddScoped<HangfireAPIService>();
            services.AddHangfire(config =>
            {
                // 自定义样式及脚本导入，必须设置为嵌入式资源
                // DashboardRoutes.AddStylesheet(typeof(Program).GetTypeInfo().Assembly, "ServerSample.Content.job.css");
                // DashboardRoutes.AddJavaScript(typeof(Program).GetTypeInfo().Assembly, "ServerSample.Content.job.js");
                // var _connection = ConnectionMultiplexer.Connect(cacheConfig.Redis.ConnectionString);

                // config.UseHeartbeatPage(checkInterval: TimeSpan.FromSeconds(1));
                //config.UseDarkModeSupportForDashboard();
                //config.UseDashboardMetrics();
                //config
                //.UseRedisStorage(_connection, new RedisStorageOptions()
                //{
                //    Db = _connection.GetDatabase().Database,
                //    FetchTimeout = TimeSpan.FromMinutes(5),
                //    Prefix = cacheConfig.Prefix,
                //    //活动服务器超时时间
                //    InvisibilityTimeout = TimeSpan.FromHours(1),
                //    //任务过期检查频率
                //    ExpiryCheckInterval = TimeSpan.FromHours(1),
                //    DeletedListSize = 10000,
                //    SucceededListSize = 10000
                //});

            });


            var listqueue = new[] { "default", "apis", "localjobs" };// 队列，必须包含默认default

            if (cacheConfig.Type == CacheType.Redis)
            {
                var redis = ConnectionMultiplexer.Connect(cacheConfig.Redis.ConnectionString);

                services.AddHangfireServer((s, op) =>
                {
                    op.ServerTimeout = TimeSpan.FromMinutes(4);
                    op.SchedulePollingInterval = TimeSpan.FromSeconds(1);// 秒级任务需要配置短点，一般任务可以配置默认时间，默认15秒
                    op.ShutdownTimeout = TimeSpan.FromMinutes(30);// 超时时间
                    op.Queues = listqueue.ToArray();// 队列
                    op.WorkerCount = Math.Max(Environment.ProcessorCount, 40);// 工作线程数，当前允许的最大线程，默认20
                    op.StopTimeout = TimeSpan.FromSeconds(20);
                }, JobStorage.Current = new RedisStorage(redis, new RedisStorageOptions()
                {
                    Db = redis.GetDatabase().Database,
                    FetchTimeout = TimeSpan.FromMinutes(5),
                    Prefix = cacheConfig.Prefix,
                    //活动服务器超时时间
                    InvisibilityTimeout = TimeSpan.FromHours(1),
                    //任务过期检查频率
                    ExpiryCheckInterval = TimeSpan.FromHours(1),
                    DeletedListSize = 10000,
                    SucceededListSize = 10000
                }));
            }
            else
            {
                services.AddHangfireServer((s, op) =>
                {
                    op.ServerTimeout = TimeSpan.FromMinutes(4);
                    op.SchedulePollingInterval = TimeSpan.FromSeconds(1);// 秒级任务需要配置短点，一般任务可以配置默认时间，默认15秒
                    op.ShutdownTimeout = TimeSpan.FromMinutes(30);// 超时时间
                    op.Queues = listqueue.ToArray();// 队列
                    op.WorkerCount = Math.Max(Environment.ProcessorCount, 40);// 工作线程数，当前允许的最大线程，默认20
                    op.StopTimeout = TimeSpan.FromSeconds(20);
                }, JobStorage.Current = new InMemoryStorage(new InMemoryStorageOptions()
                {
                    CommandTimeout = TimeSpan.FromMinutes(430),
                }));
            }


        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        public static void UseHangfire(this WebApplication app)
        {




            //app.UseHangfireDashboard("/job", new DashboardOptions
            //{
            //    AppPath = "#",// 返回时跳转的地址
            //    DisplayStorageConnectionString = true,// 是否显示数据库连接信息
            //    IsReadOnlyFunc = Context =>
            //    {
            //        var isreadonly = false;
            //        return isreadonly;
            //    },
            //    //Authorization = [restrictIpAuthorizationFilter]
            //    //AsyncAuthorization=
            //});
        }


    }

    public class HangfireDashboardAuthorization : IDashboardAuthorizationFilter
    {
        ILogger<HangfireDashboardAuthorization> _logger;
        public HangfireDashboardAuthorization(HangfireDashboardAuthorizationOptions options)
            : this(options,
       new NullLogger<HangfireDashboardAuthorization>())
        {
        }
        HangfireDashboardAuthorizationOptions _options;
        public HangfireDashboardAuthorization(HangfireDashboardAuthorizationOptions options,
            ILogger<HangfireDashboardAuthorization> logger)
        {
            ArgumentNullException.ThrowIfNull(options);
            ArgumentNullException.ThrowIfNull(logger);
            _logger = logger;
            _options = options;
        }


        public bool Authorize([NotNull] DashboardContext context)
        {
            if (_options.Users != null && _options.Users.Length > 0)
            {
                foreach (var user in _options.Users)
                {
                    if (user == context.GetHttpContext().User.Identity?.Name) return true;
                }
            }

            if (_options.Roles != null && _options.Roles.Length > 0)
            {
                foreach (var role in _options.Roles)
                {
                    if (context.GetHttpContext().User.IsInRole(role)) return true;
                }
            }

            if (_options.Claims != null && _options.Claims.Count > 0)
            {
                foreach (var item in _options.Claims)
                {
                    if (context.GetHttpContext().User.Claims.Any(x => x.Type == item.Key && x.Value == item.Value))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    public class HangfireDashboardAuthorizationOptions
    {
        public Dictionary<string, string>? Claims { get; set; }
        public string[]? Roles { get; set; }
        public string[]? Users { get; set; }
    }
}
